#region Summary 

// 
// Owner : JackieHan 
// 
// Solution : TestStringContract 
// 
// Project : CodeTimer 
// 
// File : CodeTimer.cs 
// 
// CopyRight : Copyright © 2009-2010 XunGu Corporation, All Rights Reserved 
// 
// Summary : Lao Zhao's Code Timer 
// 
// History : 
//			2010-04-26 14:49:59	    Create 
// 

#endregion

#region Using 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

#endregion

namespace CodeTimer
{
    /// <summary> 
    /// Lao Zhao's Code Timer 
    /// </summary> 
    public class CodeTimer
    {
        public static void Initialize()
        {
            Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            Time("", 1, () => { });
        }

        public static void Time(string name,int iteration,Action action)
        {
            if (string.IsNullOrEmpty(name)) return;

            ConsoleColor currentForeColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(name);

            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            int[] gcCounts = new int[GC.MaxGeneration + 1];
            for(int i=0;i<=GC.MaxGeneration;i++)
            {
                gcCounts[i] = GC.CollectionCount(i);
            }

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            ulong cycleCount = GetCycleCount();
            for (int i = 0; i < iteration; i++) action();
            ulong cpuCycle = GetCycleCount() - cycleCount;
            stopwatch.Stop();

            Console.ForegroundColor = currentForeColor;
            Console.WriteLine("\tTime Elapsed:\t" + stopwatch.ElapsedMilliseconds.ToString("N0") + "ms");
            Console.WriteLine("\tCpu Cycles:\t" + cpuCycle.ToString("N0"));

            for(int i=0;i<=GC.MaxGeneration;i++)
            {
                int count = GC.CollectionCount(i) - gcCounts[i];
                Console.WriteLine("\tGen " + i + ":\t\t" + count);
            }
        }

        public static ulong GetCycleCount()
        {
            ulong cycleCount = 0;
            QueryThreadCycleTime(GetCurrentThread(), ref cycleCount);
            return cycleCount;
        }

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetCurrentThread();
    }
}
